/**
 *
 */
package com.rf.richfitwheel.workflow.service.impl;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.rf.richfitwheel.admin.sys.vo.UserVO;
import com.rf.richfitwheel.workflow.conf.WorkflowContants;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.*;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.persistence.entity.CommentEntity;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.runtime.ProcessInstanceBuilderImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rf.richfitwheel.admin.feignclient.FSysUserService;
import com.rf.richfitwheel.admin.sys.dao.SqlAdapterMapper;
import com.rf.richfitwheel.common.exception.BusinessException;
import com.rf.richfitwheel.common.utils.BeanMapUtil;
import com.rf.richfitwheel.common.utils.DateUtils;
import com.rf.richfitwheel.common.utils.PageUtils;
import com.rf.richfitwheel.common.utils.StringUtils;
import com.rf.richfitwheel.workflow.cmd.RollbackTaskCmd;
import com.rf.richfitwheel.workflow.dao.WfCommonMapper;
import com.rf.richfitwheel.workflow.entity.HistoryProcessVo;
import com.rf.richfitwheel.workflow.entity.TaskParam;
import com.rf.richfitwheel.workflow.entity.TaskVO;
import com.rf.richfitwheel.workflow.service.DelegationService;
import com.rf.richfitwheel.workflow.service.LovelyTaskService;
import com.rf.richfitwheel.workflow.service.ModelService;

import net.sf.json.JSONObject;

/**
 * @author hushouquan
 *
 */
@Service
public class LovelyTaskServiceImpl implements LovelyTaskService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FSysUserService fSysUserService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private SqlAdapterMapper sqlAdapterMapper;// 注入dao
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private FormService formService;
    @Autowired
    private WfCommonMapper wfCommonMapper;
    @Autowired
    private ModelService modelService;
    @Autowired
    private ManagementService managerService;
    @Autowired
    private DelegationService delegationService;

    /**
     * 流程提交方法
     * @param params 参数
     * @param user 操作人
     * @return
     */
    @Override
    public TaskParam subminTask(TaskParam params, UserVO user) {
        Map<String, Object> variables = new HashMap<>();
        //创建任务
        if (params.getTaskId() == null || "".equals(params.getTaskId())) {
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(params.getProcessKey()).latestVersion().list();
            if (list.isEmpty()) {
                throw new BusinessException("没有找到相关流程定义");
            }
            ProcessInstanceBuilderImpl builder = new ProcessInstanceBuilderImpl((RuntimeServiceImpl) runtimeService);
            builder.businessKey(params.getBusNo());
            builder.tenantId(list.get(0).getTenantId());
            if (params.getBriefReport() != null && !"".equals(params.getBriefReport())) {
                builder.processInstanceName(params.getBriefReport().toString());
            } else {
                builder.processInstanceName(list.get(0).getName() + "-" + user.getStaffName() + "-" + DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
            }
            builder.processDefinitionId(list.get(0).getId());
            builder.processDefinitionKey(params.getProcessKey());
            params.wf_param.put("startUserId", params.getUser().getId());

            variables.put("wf_param", params.wf_param);//放入流程参数

            variables.putAll(params.wf_param);

            variables.put("wf_allUserID", params.getUser().getId());//放入参与人ID

            variables.put("wf_startUserName", params.getUser().getStaffName());//放入参与人姓名，用于模糊查询
            variables.put("formProperties", params.getFormProperties());
            builder.getVariables().putAll(variables);
            builder.addVariable("wf_startUserId", params.getUser().getId());
            //设置流程发起人,设置该流程启动人是和当前线程绑定的，所以线程应该是安全的
            identityService.setAuthenticatedUserId(params.getUser().getId());
            ProcessInstance instance = builder.start();//启动流程
            identityService.setAuthenticatedUserId(null);
            params.setInsId(instance.getProcessInstanceId());
            if (!params.isSkipFirstNode()) {
                Set<String> allCandidateUser = new HashSet<String>();
                List<Task> tasks = taskService.createTaskQuery().processInstanceId(instance.getProcessInstanceId()).list();
                for (Task task : tasks) {
                    task.setTenantId(builder.getTenantId());
                    taskService.saveTask(task);
                    allCandidateUser.addAll(addCandidateUser(params.getUser().getId(), task));
                }
            } else {
                List<Task> tasks = taskService.createTaskQuery().processInstanceId(instance.getProcessInstanceId()).list();
                for (Task task : tasks) {
                    task.setTenantId(builder.getTenantId());
                    //处理结果设置为发起
                    task.setDescription(WorkflowContants.ProcessResult.START.getValue());
                    taskService.saveTask(task);
                    taskService.addComment(task.getId(), task.getProcessInstanceId(), params.getDiscicription() != null ? params.getDiscicription() : "发起流程");
                    taskService.addUserIdentityLink(task.getId(), params.getUser().getId(), IdentityLinkType.STARTER);
                    taskService.setAssignee(task.getId(), params.getUser().getId());
                    taskService.complete(task.getId());
                }
                Set<String> allCandidateUser = new HashSet<String>();
                //获取新任务，重新设置审批人
                List<Task> newtasks = taskService.createTaskQuery().processInstanceId(instance.getProcessInstanceId()).list();
                for (Task task : newtasks) {
                    allCandidateUser.addAll(addCandidateUser(params.getUser().getId(), task));
                }
            }
        } else {
            taskService.claim(params.getTaskId(), params.getUser().getId());//检出任务
            if ("1".equals(params.getAuthCatagory())) {
                //如果是代理的情况，把拥有者改为授权人
                taskService.setOwner(params.getTaskId(), params.getOwner());
            }
            taskService.setVariables(params.getTaskId(), params.wf_param);
            taskService.setVariablesLocal(params.getTaskId(), params.getVariablesLocal());
            taskService.setVariableLocal(params.getTaskId(), "formProperties", params.getFormProperties());
            Task taskOld = taskService.createTaskQuery().taskId(params.getTaskId()).singleResult();
            taskOld.setDescription(params.getApproveAdvice());
            taskService.saveTask(taskOld);
            taskService.addComment(taskOld.getId(), taskOld.getProcessInstanceId(), params.getDiscicription());
            params.setInsId(taskOld.getProcessInstanceId());
            taskService.complete(taskOld.getId());
            //有需求要更新流程摘要
            if (params.getBriefReport() != null && !"".equals(params.getBriefReport())) {
                runtimeService.setProcessInstanceName(taskOld.getProcessInstanceId(), params.getBriefReport().toString());
            }
            List<Task> newtasks = taskService.createTaskQuery().processInstanceId(params.getInsId()).list();
            HistoricProcessInstance hProcessInstance = historyService.createHistoricProcessInstanceQuery().unfinished().
                    processInstanceId(params.getInsId()).singleResult();
            Set<String> allCandidateUser = new HashSet<String>();
            for (Task newtask : newtasks) {
                allCandidateUser.addAll(addCandidateUser(hProcessInstance.getStartUserId(), newtask));
            }
        }
        return params;
    }

    /**
     * <p>重新设置候选人，把策略，岗位对应的用户查询出来设置进去</p>
     * <p>Description: </p>
     *  @param startUserId 发起人
     * @param task 任务
     * @return 待办人员
     */
    private Set<String> addCandidateUser(String startUserId, Task task) {
        //返回待办人员
        Set<String> allCandidateUser = new HashSet<String>();
        // 查询流程相关人员（候选人、岗位）
        List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());
        // 所有有效的策略
        List<String> candidateGroupIdExpressions = new ArrayList<String>();
        List<String> stationIds = new ArrayList<String>();
        for (IdentityLink identityLink : identityLinkList) {
            //如果identityLink.getType()为candidate且identityLink.getGroupId()没值说明该相关人员为候选人
            if (IdentityLinkType.CANDIDATE.equals(identityLink.getType())) {
                if (identityLink.getGroupId() == null || "".equals(identityLink.getGroupId().trim())) {
                    //判断这个id是否为用户id，如果是则不作处理，不是证明是策略，那么去执行这个策略找出相关人员再把人员添加到候选人当中去
                    if (!isUser(identityLink.getUserId())) {
                        //List<String> listCandidate = getListCandidateByStrategyId(startUserId,identityLink.getUserId());
                        candidateGroupIdExpressions.add(identityLink.getUserId());
                    } else {
                        allCandidateUser.add(identityLink.getUserId());
                    }
                } else {
                    stationIds.add(identityLink.getGroupId());
                }

            }
        }

        return allCandidateUser;
    }

    /**
     * <p>判断id是否为用户</p>
     * <p>Description: </p>
     *
     * @param userId
     * @return
     */
    private boolean isUser(String userId) {
        // String querySql = "select ID_,FIRST_,LAST_ from ACT_ID_USER WHERE ID_='" + userId + "'";
        org.activiti.engine.identity.User user = identityService.createUserQuery().userId(userId).singleResult();
        // List<Map<String, Object>> list_result = sqlAdapterMapper.selectSQL(querySql);
        if (user != null) {
            return true;
        }
        return false;
    }

    /**
     * <p>根据策略返回去重后的候选人</p>
     * <p>Description: </p>
     *
     * @param startUserId
     * @return
     */
    private List<Map<String, Object>> getApproverLst(String startUserId) {
        List<Map<String, Object>> approverLst = new ArrayList<Map<String, Object>>();

        return approverLst;
    }

    @Override
    public PageUtils getToDoList(Map<String, Object> params, UserVO user) {
        int page = Integer.parseInt(params.get("page") != null ? params.get("page").toString() : "0");
        int limit = Integer.parseInt(params.get("limit") != null ? params.get("limit").toString() : "0");
        String[] tenantIds = params.get("tenantIds") != null ? params.get("tenantIds").toString().split(",") : null;
        String[] processNames = params.get("processName") != null ? params.get("processName").toString().split(",") : null;
        String userId = user.getId();
        //List<Task> tasks = WorkFlowExecution.taskService.createTaskQuery().taskAssigneeLikeIgnoreCase("%"+userId+"%").orderByTaskCreateTime().desc().listPage((page - 1) * limit, limit);
        //Long count= WorkFlowExecution.taskService.createTaskQuery().taskAssigneeLikeIgnoreCase("%"+userId+"%").count();
        List<Task> tasks = null;
        Long count = 0L;

        //如果租户ID 不为空，则查询时增加租户ID查询条件
        if (tenantIds != null && tenantIds.length > 0) {
            List<Group> groups = identityService.createGroupQuery().groupMember(userId).list();
            NativeTaskQuery taskQuery = taskService.createNativeTaskQuery();
            NativeTaskQuery taskCountQuery = taskService.createNativeTaskQuery();

            String query_sql = "SELECT DISTINCT RES.* FROM ACT_RU_TASK RES LEFT JOIN ACT_RU_IDENTITYLINK I ON I.TASK_ID_ = RES.ID_ " +
                    "LEFT JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_ WHERE  (RES.ASSIGNEE_ = #{userId} " +
                    "OR (RES.ASSIGNEE_ IS NULL AND I.TYPE_ = 'candidate' AND (I.USER_ID_ = #{userId} or I.GROUP_ID_ IN(select GROUP_ID_ from ACT_ID_MEMBERSHIP WHERE USER_ID_= #{userId})))) ";
            String count_sql = "SELECT COUNT(DISTINCT RES.ID_) FROM ACT_RU_TASK RES LEFT JOIN ACT_RU_IDENTITYLINK I ON I.TASK_ID_ = RES.ID_ " +
                    "LEFT JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_ WHERE (RES.ASSIGNEE_ = #{userId} " +
                    "OR (RES.ASSIGNEE_ IS NULL AND I.TYPE_ = 'candidate' AND (I.USER_ID_ = #{userId} or I.GROUP_ID_ IN(select GROUP_ID_ from ACT_ID_MEMBERSHIP WHERE USER_ID_= #{userId})) )) ";
            String order_sql = " ORDER BY RES.CREATE_TIME_ DESC";

            String base_or_sql = " AND (RES.TENANT_ID_ LIKE CONCAT('%', #{tenantId0}, '%') ";
            //可能传多个租户ID过来
            for (int i = 0; i < tenantIds.length; i++) {
                if (i == 0) {
                    taskQuery.parameter("tenantId0", tenantIds[i]);
                    taskCountQuery.parameter("tenantId0", tenantIds[i]);
                    continue;
                }
                base_or_sql = base_or_sql.concat("OR RES.TENANT_ID_ LIKE CONCAT('%', #{tenantId" + i + "}, '%')");
                taskQuery.parameter("tenantId" + i, tenantIds[i]);
                taskCountQuery.parameter("tenantId" + i, tenantIds[i]);
            }
            base_or_sql = base_or_sql.concat(") ");
            query_sql = query_sql.concat(base_or_sql);
            count_sql = count_sql.concat(base_or_sql);
            //如果流程名称不为空，则增加查询条件
            if (StringUtils.isNotBlank(processNames)) {

                String processName_sql = "AND DEF.NAME_ IN (";
                for (int i = 0; i < processNames.length; i++) {
                    processName_sql = processName_sql.concat("#{processName" + i + "}");
                    if (i != processNames.length - 1) {
                        processName_sql = processName_sql.concat(",");
                    }
                    taskQuery.parameter("processName" + i, processNames[i]);
                    taskCountQuery.parameter("processName" + i, processNames[i]);
                }
                processName_sql = processName_sql.concat(") ");
                query_sql = query_sql.concat(processName_sql);
                count_sql = count_sql.concat(processName_sql);
            }
            tasks = taskQuery.sql(query_sql.concat(order_sql)).parameter("userId", userId).listPage((page - 1) * limit, limit);
            count = taskCountQuery.sql(count_sql).parameter("userId", userId).count();
        } else {
            tasks = taskService.createTaskQuery()
                    .taskCandidateOrAssigned(userId).orderByTaskCreateTime().desc().listPage((page - 1) * limit, limit);
            count = taskService.createTaskQuery().taskCandidateOrAssigned(userId).count();
        }
        List<TaskVO> taskVOS = new LinkedList<TaskVO>();
        for (Task task : tasks) {
            //ProcessInstance  processInstance= WorkFlowExecution.runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            HistoricProcessInstance hProcessInstance = historyService.createHistoricProcessInstanceQuery().unfinished().
                    processInstanceId(task.getProcessInstanceId()).singleResult();

            Map<String, Object> variable = taskService.getVariables(task.getId());

            ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
            ProcessDefinition processDefinition = processDefinitionQuery.processDefinitionId(hProcessInstance.getProcessDefinitionId()).singleResult();
            Object returnSign = variable.get("returnSign");
            Map<String, Object> wf_param = (Map<String, Object>) variable.get("wf_param");
            boolean returnSign_b = returnSign != null ? Boolean.parseBoolean(returnSign.toString()) : false;//是否退回节点
            TaskVO taskVO = new TaskVO(task);

//             User assiginObjec = fSysUserAuthService.getUserById(task.getAssignee());
//             if (assiginObjec!=null) {
//                     taskVO.setAssigneename(((User) assiginObjec).getStaffName());
//             }

            String submitTime = DateUtils.format(task.getCreateTime(), DateUtils.DATE_TIME_PATTERN);
            taskVO.setSubmitTime(submitTime);
            String querySql = "select ID_ as userId,FIRST_,LAST_ as username from ACT_ID_USER WHERE ID_  ='" + hProcessInstance.getStartUserId() + "'";
            List<Map<String, Object>> list_result = sqlAdapterMapper.selectSQL(querySql);
            if (!list_result.isEmpty()) {
                taskVO.setStartUser(list_result.get(0).get("username").toString());
            }

            // taskVO.setSuspended(processInstance.isSuspended());
            taskVO.setBusNo(hProcessInstance.getBusinessKey());
            taskVO.setWf_param(wf_param);
            taskVO.setReturnSign(returnSign_b);
            taskVO.setProcessName(hProcessInstance.getProcessDefinitionName());
            taskVO.setBriefReport(hProcessInstance.getName());

            if (processDefinition != null) {
                taskVO.setDetailPage(processDefinition.getCategory().toString());
            }
            taskVOS.add(taskVO);

        }
        PageUtils pageUtils = new PageUtils(taskVOS, count.intValue());
        return pageUtils;
    }

    /**
     * 别人授权给自己处理的流程
     * @param params
     * @return
     */
    @Override
    public PageUtils getAuthorizationTaskList(Map<String, Object> params) {
        int page = Integer.parseInt(params.get("page") != null ? params.get("page").toString() : "0");
        int limit = Integer.parseInt(params.get("limit") != null ? params.get("limit").toString() : "0");
        String tenantId = StringUtils.isNotBlank(params.get("tenantIds")) ? params.get("tenantIds").toString().trim() : null;
        String userId = params.get("sessionUserId").toString();
        String nowString = DateUtils.format(new Date(), "yyyy-MM-dd") + " 00:00:00";
        String endString = DateUtils.format(new Date(), "yyyy-MM-dd") + " 23:59:59";
       /*  String deleSql = "select del.id,del.auth_id,del.be_auth_id,del.auth_catagory,DATE_FORMAT(del.start_time,'%Y-%m-%d') as start_time ,DATE_FORMAT(del.end_time,'%Y-%m-%d') as end_time,u.staff_name as assigneename ,del.reason " +
                " from wf_delegation del,sys_user u where del.auth_id=u.id and be_auth_id='" + userId + "' and ( start_time <= STR_TO_DATE('" + nowString + "','%Y-%m-%d %H:%i:%S')  and end_time >= STR_TO_DATE('" + nowString + "','%Y-%m-%d %H:%i:%S'))";
        List<Map<String, Object>>  delegations = sqlAdapterMapper.selectSQL(deleSql); */
        Map<String, Object> pp = new HashMap<String, Object>();
        pp.put("userId", userId);
        pp.put("nowString", nowString);
        pp.put("endString", endString);
        List<Map<String, Object>> delegations = delegationService.getDelegationByUserIdAndTime(pp);
        List<TaskVO> taskVOS = new LinkedList<TaskVO>();
        Map<String, TaskVO> taskVOSMap = new LinkedHashMap<String, TaskVO>();
        for (Map<String, Object> delegation : delegations) {
            List<Map<String, Object>> tasks = new ArrayList<>();
            String aTaskSql = getAuthorizationTaskListSql(tenantId, delegation.get("auth_id").toString());
            tasks = sqlAdapterMapper.selectSQL(aTaskSql);
            for (Map<String, Object> task : tasks) {
                TaskVO taskVO = new TaskVO();
                taskVO.setId(task.get("ID_").toString());
                taskVO.setKey(task.get("TASK_DEF_KEY_") == null ? null : task.get("TASK_DEF_KEY_").toString());
                taskVO.setName(task.get("NAME_") == null ? null : task.get("NAME_").toString());
                taskVO.setDescription(task.get("DESCRIPTION_") == null ? null : task.get("DESCRIPTION_").toString());
                taskVO.setAssignee(delegation.get("auth_id").toString());
                taskVO.setFormKey(task.get("FORM_KEY_") == null ? null : task.get("FORM_KEY_").toString());
                taskVO.setProcessId(task.get("PROC_INST_ID_").toString());
                taskVO.setProcessDefinitionId(task.get("PROC_DEF_ID_").toString());
                taskVO.setExecutionId(task.get("EXECUTION_ID_").toString());
                taskVO.setTaskDefinitionKey(task.get("TASK_DEF_KEY_").toString());
                taskVO.setBusNo(task.get("BUSINESS_KEY_") == null ? null : task.get("BUSINESS_KEY_").toString());
                taskVO.setProcessName(task.get("PROC_DEF_NAME_").toString());
                String submitTime = DateUtils.format((Date) task.get("CREATE_TIME_"), DateUtils.DATE_TIME_PATTERN);
                taskVO.setSubmitTime(submitTime);
                taskVO.setAssigneename(delegation.get("assigneename") == null ? null : delegation.get("assigneename").toString());
                taskVO.setStartUser(task.get("startUser") == null ? null : task.get("startUser").toString());
                taskVO.setBriefReport(task.get("briefReport") == null ? null : task.get("briefReport").toString());
//                taskVO.setReturnSign(returnSign_b);
                taskVO.setDetailPage(task.get("detailPage") == null ? null : task.get("detailPage").toString());
                taskVO.setReason(delegation.get("reason") == null ? null : delegation.get("reason").toString());
                //处理流程变量
                Map<String, Object> variable = taskService.getVariables(task.get("ID_").toString());
                Map<String, Object> wf_param = (Map<String, Object>) variable.get("wf_param");
                taskVO.setWf_param(wf_param);
                //授权处理的流程中用到：1-一般性代理、2-访问查看
                taskVO.setAuthCatagory(delegation.get("auth_catagory").toString());
                //用map去重
                taskVOSMap.put(taskVO.getId(), taskVO);
            }
        }
        taskVOS = taskVOSMap.values().stream().collect(Collectors.toList());
        List<TaskVO> taskVOSPage = new LinkedList<TaskVO>();
        int count = taskVOS.size();
        if (count == 0) {
            //不分页
        } else {
            taskVOSPage = taskVOS.subList(page > 0 ? ((page - 1) * limit) : 0, (page * limit) > count ? count : (page * limit));
        }
        PageUtils pageUtils = new PageUtils(taskVOSPage, count);
        return pageUtils;
    }

    private String getAuthorizationTaskListSql(String tenantId, String auth_id) {
        StringBuffer dsb = new StringBuffer();
        dsb.append("select distinct RES.*,HI.BUSINESS_KEY_,HI.START_USER_ID_,HI.NAME_ AS briefReport, DEF.KEY_ as PROC_DEF_KEY_, DEF.NAME_ as PROC_DEF_NAME_, DEF.VERSION_ as PROC_DEF_VERSION_, DEF.DEPLOYMENT_ID_ as DEPLOYMENT_ID_,DEF.CATEGORY_ AS detailPage,u.LAST_ as startUser    from ACT_RU_TASK RES ");
        dsb.append(" left join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
        dsb.append(" left join ACT_HI_PROCINST HI on RES.PROC_INST_ID_ = HI.PROC_INST_ID_");
        dsb.append(" left outer join ACT_RE_PROCDEF DEF on RES.PROC_DEF_ID_ = DEF.ID_");
        dsb.append(" left join ACT_ID_USER u on HI.START_USER_ID_=u.ID_");
        dsb.append(" WHERE  RES.TENANT_ID_ = '" + tenantId + "'");
        dsb.append(" and (RES.ASSIGNEE_ = '" + auth_id + "'");
        dsb.append(" or (RES.ASSIGNEE_ is null");
        dsb.append(" and I.TYPE_ = 'candidate' and (I.USER_ID_ = '" + auth_id + "'");
        dsb.append(" or I.GROUP_ID_ IN(");
        dsb.append(" select GROUP_ID_ from ACT_ID_MEMBERSHIP WHERE USER_ID_='" + auth_id + "'");
        dsb.append(" )))) order by RES.CREATE_TIME_ desc");
        return dsb.toString();
    }

    /**
     * 查询当前任务节点信息
     * @param taskId
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getTaskNodeInfo(String taskId) throws Exception {
//		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        TaskFormData taskFormData = formService.getTaskFormData(taskId);
        //获取task对应的表单内容
        UserTask userTask = (UserTask) repositoryService.getBpmnModel(taskFormData.getTask().getProcessDefinitionId())
                .getFlowElement(taskFormData.getTask().getTaskDefinitionKey());
        List<FormProperty> formProperties = userTask.getFormProperties();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("task", taskFormData.getTask());
        List<Object> list = new ArrayList<Object>();
        for (org.activiti.engine.form.FormProperty pop : taskFormData.getFormProperties()) {
            Map newMap = BeanMapUtil.bean2map(pop);
            for (FormProperty pp : formProperties) {
                if (pop.getName().equals(pp.getName())) {
                    newMap.put("formValues", pp.getFormValues());
                }
            }
            list.add(newMap);
        }
        map.put("formProperties", list);
        return map;
    }

    /**
     * 根据业务id查询流程处理记录
     * @param busNo
     * @return
     */
    @Override
    public List<Map<String, Object>> getApproveHistoryByBusNo(String busNo) {
        List<Map<String, Object>> taskList = new LinkedList<Map<String, Object>>();
        //改为直接查结束的任务，终止的任务已处理成与正常结束的一样的道理即把终止原因存入Comment
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .processInstanceBusinessKey(busNo).finished().orderByTaskCreateTime()
                .desc().list();
        //未结束的任务需要单独处理下审批人
        List<HistoricTaskInstance> list_unfinish = historyService.createHistoricTaskInstanceQuery()
                .processInstanceBusinessKey(busNo)
                .unfinished().orderByTaskCreateTime()
                .desc().list();

        for (int i = 0; i < list_unfinish.size(); i++) {

            HistoricTaskInstance hai = list_unfinish.get(i);
            List<Comment> comments = taskService.getTaskComments(hai.getId());
            Map<String, Object> _map = new LinkedHashMap<String, Object>();
            //如果是多实例可能出现多任务情况（会签）
            List<Task> tasks = taskService.createTaskQuery().processInstanceBusinessKey(busNo).list();
//			System.out.println("办理人：" + hai.getAssignee());
            //改为候选人
            List<IdentityLink> identityLinkListAll = new ArrayList<IdentityLink>();
            for (Task task : tasks) {
                List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());
                identityLinkListAll.addAll(identityLinkList);
            }
            List<String> listUQ = new ArrayList<String>();
            for (IdentityLink identityLink : identityLinkListAll) {
                if (identityLink.getUserId() != null) {
                    listUQ.add(identityLink.getUserId());
                }
            }

            StringBuffer inPram = new StringBuffer();
            for (String ss : listUQ) {
                inPram.append("'" + ss + "',");
            }
            String inp = inPram.toString().substring(0, inPram.toString().length() - 1);
            String querySql = "select ID_ as userId,FIRST_,LAST_ as username from ACT_ID_USER WHERE ID_ in(" + inp + ")";
            List<Map<String, Object>> assiginObjecs = sqlAdapterMapper.selectSQL(querySql);
            String assignee = "";
            String assigneeName = "";
            Iterator<Map<String, Object>> iterator = assiginObjecs.iterator();

            for (; iterator.hasNext(); ) {
                Map<String, Object> assiginObjec = iterator.next();
                if (iterator.hasNext()) {
                    assignee += assiginObjec.get("userId") + ",";
                    assigneeName += assiginObjec.get("username") + ",";
                } else {
                    assignee += assiginObjec.get("userId");
                    assigneeName += assiginObjec.get("username");
                }
            }

            if (assiginObjecs != null) {
                _map.put("assigneeName", assigneeName);
            }
            if (assignee != null) {
                _map.put("assignee", assignee);
            }
            System.out.println("活动ID:" + hai.getId());
            _map.put("actId", hai.getId());
            _map.put("activityDfId", hai.getTaskDefinitionKey());
            System.out.println("流程实例ID:" + hai.getProcessInstanceId());
            _map.put("taskId", hai.getProcessInstanceId());
            System.out.println("活动名称：" + hai.getName());
            _map.put("actName", hai.getName());
            System.out.println("开始时间：" + DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));
            _map.put("startTime", DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));

            System.out.println("结束时间：" + hai.getEndTime());
            if (hai.getEndTime() != null) {
                _map.put("endTime", DateUtils.format(hai.getEndTime(), DateUtils.DATE_TIME_PATTERN));
                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSED.getValue());
            } else {

                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSING.getValue());

            }

            //处理意见
            for (Comment cmt : comments) {
                _map.put("description", ((CommentEntity) cmt).getFullMessage());
            }

            //审批意见
            _map.put("aproveAdvice", hai.getDescription());
            taskList.add(_map);
        }

        for (int i = 0; i < list.size(); i++) {
            HistoricTaskInstance hai = list.get(i);
            List<Comment> comments = taskService.getTaskComments(hai.getId());
            Map<String, Object> _map = new LinkedHashMap<String, Object>();
            if (hai.getAssignee() == null || "".equals(hai.getAssignee())) {
                continue;
            }
            _map.put("assignee", hai.getAssignee());
// 			List<User> assiginObjecs = fSysUserAuthService.getUserByIds(Arrays.asList( hai.getAssignee().split(",")));
            StringBuffer inPram = new StringBuffer();
            for (String ss : Arrays.asList(hai.getAssignee().split(","))) {
                inPram.append("'" + ss + "',");
            }
            String inp = inPram.toString().substring(0, inPram.toString().length() - 1);
            String querySql = "select ID_ as userId,FIRST_,LAST_ as username from ACT_ID_USER WHERE ID_ in(" + inp + ")";
            List<Map<String, Object>> assiginObjecs = sqlAdapterMapper.selectSQL(querySql);
            String assigneeName = "";
            Iterator<Map<String, Object>> iterator = assiginObjecs.iterator();

            for (; iterator.hasNext(); ) {
                Map<String, Object> assiginObjec = iterator.next();
                if (iterator.hasNext()) {
                    if (StringUtils.isNotBlank(hai.getOwner())) {
                        assigneeName += assiginObjec.get("username") + "(代)" + ",";
                    } else {
                        assigneeName += assiginObjec.get("username") + ",";
                    }
                } else {
                    if (StringUtils.isNotBlank(hai.getOwner())) {
                        assigneeName += assiginObjec.get("username") + "(代)";
                    } else {
                        assigneeName += assiginObjec.get("username");
                    }
                }
            }

            if (assiginObjecs != null) {
                _map.put("assigneeName", assigneeName);
            }

            System.out.println("活动ID:" + hai.getId());
            _map.put("actId", hai.getId());
            _map.put("activityDfId", hai.getTaskDefinitionKey());
            System.out.println("流程实例ID:" + hai.getProcessInstanceId());
            _map.put("taskId", hai.getProcessInstanceId());
            System.out.println("活动名称：" + hai.getName());
            _map.put("actName", hai.getName());
            System.out.println("开始时间：" + DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));
            _map.put("startTime", DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));

            System.out.println("结束时间：" + hai.getEndTime());
            if (hai.getEndTime() != null) {
                _map.put("endTime", DateUtils.format(hai.getEndTime(), DateUtils.DATE_TIME_PATTERN));
                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSED.getValue());
            } else {

                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSING.getValue());

            }

            //处理意见
            for (Comment cmt : comments) {
                // _map.put("description", ((CommentEntity)cmt).getMessage());
                //解决处理意见超长展示不全问题
                _map.put("description", ((CommentEntity) cmt).getFullMessage());
            }

            //审批意见
            _map.put("aproveAdvice", hai.getDescription());
            taskList.add(_map);
        }

        return taskList;
    }

    /**
     * 根据流程实例id查询流程处理记录
     * @param processId
     * @return
     */
    @Override
    public List<Map<String, Object>> getApproveHistoryByProcessId(String processId) {
        List<Map<String, Object>> taskList = new LinkedList<Map<String, Object>>();
        //改为直接查结束的任务，终止的任务已处理成与正常结束的一样的道理即把终止原因存入Comment
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processId)
                .finished().orderByTaskCreateTime().desc().list();
        //未结束的任务需要单独处理下审批人
        List<HistoricTaskInstance> list_unfinish = historyService.createHistoricTaskInstanceQuery().processInstanceId(processId)
                .unfinished().orderByTaskCreateTime().desc().list();

        for (int i = 0; i < list_unfinish.size(); i++) {

            HistoricTaskInstance hai = list_unfinish.get(i);
            List<Comment> comments = taskService.getTaskComments(hai.getId());
            Map<String, Object> _map = new LinkedHashMap<String, Object>();
            //如果是多实例可能出现多任务情况（会签）
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(processId).list();
//			System.out.println("办理人：" + hai.getAssignee());
            //改为候选人
            List<IdentityLink> identityLinkListAll = new ArrayList<IdentityLink>();
            for (Task task : tasks) {
                List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());
                identityLinkListAll.addAll(identityLinkList);
            }
            List<String> listUQ = new ArrayList<String>();
            for (IdentityLink identityLink : identityLinkListAll) {
                if (identityLink.getUserId() != null) {
                    listUQ.add(identityLink.getUserId());
                }
            }

            StringBuffer inPram = new StringBuffer();
            for (String ss : listUQ) {
                inPram.append("'" + ss + "',");
            }
            String assignee = "";
            String assigneeName = "";
            if (!listUQ.isEmpty()) {
                String inp = inPram.toString().substring(0, inPram.toString().length() - 1);
                String querySql = "select ID_ as userId,FIRST_,LAST_ as username from ACT_ID_USER WHERE ID_ in(" + inp + ")";
                List<Map<String, Object>> assiginObjecs = sqlAdapterMapper.selectSQL(querySql);
                Iterator<Map<String, Object>> iterator = assiginObjecs.iterator();

                for (; iterator.hasNext(); ) {
                    Map<String, Object> assiginObjec = iterator.next();
                    if (iterator.hasNext()) {
                        assignee += assiginObjec.get("userId") + ",";
                        assigneeName += assiginObjec.get("username") + ",";
                    } else {
                        assignee += assiginObjec.get("userId");
                        assigneeName += assiginObjec.get("username");
                    }
                }
            }

            if (assigneeName != null) {
                _map.put("assigneeName", assigneeName);
            }
            if (assignee != null) {
                _map.put("assignee", assignee);
            }
            System.out.println("活动ID:" + hai.getId());
            _map.put("actId", hai.getId());
            _map.put("activityDfId", hai.getTaskDefinitionKey());
            System.out.println("流程实例ID:" + hai.getProcessInstanceId());
            _map.put("taskId", hai.getProcessInstanceId());
            System.out.println("活动名称：" + hai.getName());
            _map.put("actName", hai.getName());
            System.out.println("开始时间：" + DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));
            _map.put("startTime", DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));

            System.out.println("结束时间：" + hai.getEndTime());
            if (hai.getEndTime() != null) {
                _map.put("endTime", DateUtils.format(hai.getEndTime(), DateUtils.DATE_TIME_PATTERN));
                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSED.getValue());
            } else {

                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSING.getValue());

            }

            //处理意见
            for (Comment cmt : comments) {
                _map.put("description", ((CommentEntity) cmt).getFullMessage());
            }

            //审批意见
            _map.put("aproveAdvice", hai.getDescription());
            taskList.add(_map);
        }

        for (int i = 0; i < list.size(); i++) {
            HistoricTaskInstance hai = list.get(i);
            List<Comment> comments = taskService.getTaskComments(hai.getId());
            Map<String, Object> _map = new LinkedHashMap<String, Object>();
            if (hai.getAssignee() == null || "".equals(hai.getAssignee())) {
                continue;
            }
            _map.put("assignee", hai.getAssignee());
// 			List<User> assiginObjecs = fSysUserAuthService.getUserByIds(Arrays.asList( hai.getAssignee().split(",")));
            StringBuffer inPram = new StringBuffer();
            for (String ss : Arrays.asList(hai.getAssignee().split(","))) {
                inPram.append("'" + ss + "',");
            }
            String inp = inPram.toString().substring(0, inPram.toString().length() - 1);
            String querySql = "select ID_ as userId,FIRST_,LAST_ as username from ACT_ID_USER WHERE ID_ in(" + inp + ")";
            List<Map<String, Object>> assiginObjecs = sqlAdapterMapper.selectSQL(querySql);
            String assigneeName = "";
            Iterator<Map<String, Object>> iterator = assiginObjecs.iterator();

            for (; iterator.hasNext(); ) {
                Map<String, Object> assiginObjec = iterator.next();
                if (iterator.hasNext()) {
                    if (StringUtils.isNotBlank(hai.getOwner())) {
                        assigneeName += assiginObjec.get("username") + "(代)" + ",";
                    } else {
                        assigneeName += assiginObjec.get("username") + ",";
                    }
                } else {
                    if (StringUtils.isNotBlank(hai.getOwner())) {
                        assigneeName += assiginObjec.get("username") + "(代)";
                    } else {
                        assigneeName += assiginObjec.get("username");
                    }
                }
            }

            if (assiginObjecs != null) {
                _map.put("assigneeName", assigneeName);
            }

            System.out.println("活动ID:" + hai.getId());
            _map.put("actId", hai.getId());
            _map.put("activityDfId", hai.getTaskDefinitionKey());
            System.out.println("流程实例ID:" + hai.getProcessInstanceId());
            _map.put("taskId", hai.getProcessInstanceId());
            System.out.println("活动名称：" + hai.getName());
            _map.put("actName", hai.getName());
            System.out.println("开始时间：" + DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));
            _map.put("startTime", DateUtils.format(hai.getStartTime(), DateUtils.DATE_TIME_PATTERN));

            System.out.println("结束时间：" + hai.getEndTime());
            if (hai.getEndTime() != null) {
                _map.put("endTime", DateUtils.format(hai.getEndTime(), DateUtils.DATE_TIME_PATTERN));
                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSED.getValue());
            } else {

                _map.put("state", WorkflowContants.ProcessRecordState.PROCESSING.getValue());

            }

            //处理意见
            for (Comment cmt : comments) {
                // _map.put("description", ((CommentEntity)cmt).getMessage());
                //解决处理意见超长展示不全问题
                _map.put("description", ((CommentEntity) cmt).getFullMessage());
            }

            //审批意见
            _map.put("aproveAdvice", hai.getDescription());
            taskList.add(_map);
        }

        return taskList;
    }

    /**
     * 获取可退回节点
     * @param processId
     * @param taskDefinitionKey
     * @param processDefinitionId
     * @return
     */
    @Override
    public List<Map<String, Object>> getRetractNode(String processId, String taskDefinitionKey,
                                                    String processDefinitionId) {
        Set<String> keys = new HashSet<String>();
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService
                .getProcessDefinition(processDefinitionId);
        // 当前节点
        ActivityImpl currentActivity = processDefinitionEntity.findActivity(taskDefinitionKey); // 根据活动id获取活动实例
        String reBackNodeKey = currentActivity.getProperty("documentation") == null ? null : currentActivity.getProperty("documentation").toString();
        List<Map<String, Object>> taskList = new LinkedList<Map<String, Object>>();
        if (reBackNodeKey == null || "".equals(reBackNodeKey)) {
            return taskList;
        }
        String[] reBackNodeKeyArry = reBackNodeKey.split(",");

        for (String setting : reBackNodeKeyArry) {

            List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery() // 历史相关Service
                    .taskDefinitionKey(setting)
                    .processInstanceId(processId)
                    .finished()
                    .taskDeleteReason("completed").list();

            for (int i = 0; i < tasks.size(); i++) {
                HistoricTaskInstance hai = tasks.get(i);

                Map<String, Object> _map = new LinkedHashMap<String, Object>();

                System.out.println("办理人：" + hai.getAssignee());
                _map.put("assignee", hai.getAssignee());


                if (keys.contains(hai.getTaskDefinitionKey())) {
                    continue;
                } else {
                    keys.add(hai.getTaskDefinitionKey());
                }

                System.out.println("活动ID:" + hai.getId());

                _map.put("actId", hai.getId());
                _map.put("activityDfId", hai.getTaskDefinitionKey());

                System.out.println("流程实例ID:" + hai.getProcessInstanceId());
                _map.put("taskId", hai.getProcessInstanceId());

                System.out.println("活动名称：" + hai.getName());
                _map.put("actName", hai.getName());

                taskList.add(_map);
            }
        }
        return taskList;
    }

    /**
     * 获取审批意见
     * @param taskId
     * @return
     */
    @Override
    public String getApproveAdviceByTaskId(String taskId) {
        List<Comment> comments = taskService.getTaskComments(taskId, "comment");
        if (!comments.isEmpty()) {
            return comments.get(0).getFullMessage();
        }
        return "";
    }

    /**
     * 我参与的流程
     * @param page
     * @param limit
     * @param dataForm
     * @param userId
     * @return
     */
    @Override
    public PageUtils queryParticipationProcessList(String page, String limit, String dataForm, String userId) {
        int pageq = Integer.parseInt(page != null ? page : "0");
        int limitq = Integer.parseInt(limit != null ? limit : "0");
        Page<Map<String, Object>> p = PageHelper.startPage(pageq, limitq);
        JSONObject obj = StringUtils.isBlank(dataForm) ? null : JSONObject.fromObject(dataForm);
        Map<String, Object> pram = new HashMap<String, Object>();
        pram.put("userId", userId);
        if (obj != null) {
            if (obj.containsKey("processName") && StringUtils.isNotBlank(obj.get("processName"))) {
                pram.put("processName", "%" + obj.getString("processName").trim() + "%");
            }
//            if (obj.containsKey("tenantIds") && StringUtils.isNotBlank(obj.get("tenantIds"))) {
//                pram.put("tenantIds", obj.getString("tenantIds").trim().split(","));
//            }
            //流程状态
            if (obj.containsKey("state") && StringUtils.isNotBlank(obj.get("state"))) {
                switch (obj.getString("state")) {
                    case "0":
                        pram.put("stateSql", "ins.END_TIME_ IS NULL");
                        break;
                    case "1":
                        pram.put("stateSql", "ins.END_TIME_ IS NOT NULL AND ins.DELETE_REASON_ IS NULL");
                        break;
                    case "2":
                        pram.put("stateSql", "ins.END_TIME_ IS NOT NULL AND ins.DELETE_REASON_ IS NOT NULL");
                        break;
                    default:
                        break;
                }
            }
            if (obj.containsKey("startTime") && StringUtils.isNotBlank(obj.get("startTime"))) {
                String startTime = obj.getString("startTime");
                Date dateF = null;
                Date dateT = null;
                if (!startTime.startsWith("F") && !startTime.contains("T")) { //非日期范围
                    dateT = DateUtils.setDateTwoThree(new Date());
                    dateF = DateUtils.setDateZero(DateUtils.addDateDays(dateT, -Integer.parseInt(startTime)));
                } else {//日期范围
                    List<Date> dates = DateUtils.fromDateToDate(startTime);
                    dateF = dates.get(0);
                    dateT = dates.get(1);
                }
                pram.put("startDateF", dateF);
                pram.put("startDateT", dateT);
            }
            if (obj.containsKey("endTime") && StringUtils.isNotBlank(obj.get("endTime"))) {
                String endTime = obj.getString("endTime");
                Date dateF = null;
                Date dateT = null;
                //非日期范围
                if (!endTime.startsWith("F") && !endTime.contains("T")) {
                    dateT = DateUtils.setDateTwoThree(new Date());
                    dateF = DateUtils.setDateZero(DateUtils.addDateDays(dateT, -Integer.parseInt(endTime)));
                } else {//日期范围
                    List<Date> dates = DateUtils.fromDateToDate(endTime);
                    dateF = dates.get(0);
                    dateT = dates.get(1);
                }
                pram.put("endDateF", dateF);
                pram.put("endDateT", dateT);
            }
        }
        List<Map<String, Object>> list = wfCommonMapper.getParticipantTask(pram);
        PageUtils pageUtils = new PageUtils(p);
        return pageUtils;
    }


    /**
     * 我创建的流程-sql组装
     *
     * @param obj
     * @param processInstanceQuery
     * @param processInstanceCount
     */
    private Map<String, String> assembleSql(JSONObject obj, NativeHistoricProcessInstanceQuery processInstanceQuery, NativeHistoricProcessInstanceQuery processInstanceCount) {
        String[] tenantIds = StringUtils.isNotBlank(obj.get("tenantIds")) ? obj.get("tenantIds").toString().split(",") : null;

        String query_sql = "SELECT DISTINCT RES.*, DEF.KEY_ AS PROC_DEF_KEY_, DEF.NAME_ AS PROC_DEF_NAME_,DEF.VERSION_ AS PROC_DEF_VERSION_,DEF.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_ " +
                "FROM ACT_HI_PROCINST RES LEFT OUTER JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_ WHERE RES.START_USER_ID_ = #{userId} ";
        String count_sql = "SELECT  COUNT(DISTINCT RES.ID_) " +
                "FROM ACT_HI_PROCINST RES LEFT OUTER JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_ WHERE RES.START_USER_ID_ = #{userId} ";
        String order_sql = " ORDER BY RES.START_TIME_ DESC";
//        if (tenantIds != null) {
//            String base_or_sql = "AND (RES.TENANT_ID_ LIKE CONCAT('%', #{tenantId0}, '%') ";
//            for (int i = 0; i < tenantIds.length; i++) { // 多个租户ID处理
//                if (i == 0) {
//                    processInstanceQuery.parameter("tenantId0", tenantIds[i]);
//                    processInstanceCount.parameter("tenantId0", tenantIds[i]);
//                    continue;
//                }
//                base_or_sql = base_or_sql.concat("OR RES.TENANT_ID_ LIKE CONCAT('%', #{tenantId" + i + "}, '%')");
//                processInstanceQuery.parameter("tenantId" + i, tenantIds[i]);
//                processInstanceCount.parameter("tenantId" + i, tenantIds[i]);
//            }
//            base_or_sql = base_or_sql.concat(") ");
//            query_sql = query_sql.concat(base_or_sql);
//            count_sql = count_sql.concat(base_or_sql);
//        }
        //查询条件
        if (obj.containsKey("processName") && StringUtils.isNotBlank(obj.get("processName"))) {
            String[] processNames = obj.getString("processName").split(",");
            String in_sql = "";
            for (int i = 0; i < processNames.length; i++) {
                in_sql = in_sql.concat("#{processName" + i + "}");
                processInstanceQuery.parameter("processName" + i, processNames[i]);
                processInstanceCount.parameter("processName" + i, processNames[i]);

                if (i < processNames.length - 1) {
                    in_sql = in_sql.concat(",");
                }
            }
            query_sql = query_sql.concat("AND DEF.NAME_ IN (" + in_sql + ")");
            count_sql = count_sql.concat("AND DEF.NAME_ IN (" + in_sql + ")");
        }
        //摘要
        if (obj.containsKey("briefReport") && StringUtils.isNotBlank(obj.get("briefReport"))) {
            query_sql = query_sql.concat("AND RES.NAME_ like #{briefReport} ");
            count_sql = count_sql.concat("AND RES.NAME_ like #{briefReport} ");
            processInstanceQuery.parameter("briefReport", "%" + obj.getString("briefReport").trim() + "%");
            processInstanceCount.parameter("briefReport", "%" + obj.getString("briefReport").trim() + "%");
        }
        //流程状态
        if (obj.containsKey("state") && StringUtils.isNotBlank(obj.getString("state"))) {
            switch (obj.getString(("state"))) {
                case "0":
                    query_sql = query_sql.concat(" AND RES.END_TIME_ IS NULL");
                    count_sql = count_sql.concat(" AND RES.END_TIME_ IS NULL");
                    break;
                case "1":
                    query_sql = query_sql.concat(" AND RES.END_TIME_ IS NOT NULL AND RES.DELETE_REASON_ IS NULL ");
                    count_sql = count_sql.concat(" AND RES.END_TIME_ IS NOT NULL AND RES.DELETE_REASON_ IS NULL ");
                    break;
                case "2":
                    query_sql = query_sql.concat(" AND RES.END_TIME_ IS NOT NULL AND RES.DELETE_REASON_ IS NOT NULL ");
                    count_sql = count_sql.concat(" AND RES.END_TIME_ IS NOT NULL AND RES.DELETE_REASON_ IS NOT NULL ");
                default:
                    break;
            }
        }
        //开始时间
        if (obj.containsKey("startTime") && StringUtils.isNotBlank(obj.getString("startTime"))) {
            String startTime = obj.getString("startTime");
            Date dateF = null;
            Date dateT = null;
            //非日期范围
            if (!startTime.startsWith("F") && !startTime.contains("T")) {
                dateT = DateUtils.setDateTwoThree(new Date());
                dateF = DateUtils.setDateZero(DateUtils.addDateDays(dateT, -Integer.parseInt(startTime)));
            } else {//日期范围
                List<Date> dates = DateUtils.fromDateToDate(startTime);
                dateF = dates.get(0);
                dateT = dates.get(1);
            }
            query_sql = query_sql.concat(" AND RES.START_TIME_ BETWEEN #{startDateF} AND #{startDateT}");
            count_sql = count_sql.concat(" AND RES.START_TIME_ BETWEEN #{startDateF} AND #{startDateT}");
            processInstanceQuery.parameter("startDateF", dateF);
            processInstanceQuery.parameter("startDateT", dateT);
            processInstanceCount.parameter("startDateF", dateF);
            processInstanceCount.parameter("startDateT", dateT);
        }
        //结束时间
        if (obj.containsKey("endTime") && StringUtils.isNotBlank(obj.getString("endTime"))) {
            String endTime = obj.getString("endTime");
            Date dateF = null;
            Date dateT = null;
            //非日期范围
            if (!endTime.startsWith("F") && !endTime.contains("T")) {
                dateT = DateUtils.setDateTwoThree(new Date());
                dateF = DateUtils.setDateZero(DateUtils.addDateDays(dateT, -Integer.parseInt(endTime)));
            } else {                                                   //日期范围
                List<Date> dates = DateUtils.fromDateToDate(endTime);
                dateF = dates.get(0);
                dateT = dates.get(1);
            }
            query_sql = query_sql.concat(" AND RES.END_TIME_ BETWEEN #{endDateF} AND #{endDateT}");
            count_sql = count_sql.concat(" AND RES.END_TIME_ BETWEEN #{endDateF} AND #{endDateT}");
            processInstanceQuery.parameter("endDateF", dateF);
            processInstanceQuery.parameter("endDateT", dateT);
            processInstanceCount.parameter("endDateF", dateF);
            processInstanceCount.parameter("endDateT", dateT);
        }
        query_sql = query_sql.concat(order_sql);
        Map<String, String> queryMap = new HashMap<>(2);
        queryMap.put("query", query_sql);
        queryMap.put("count", count_sql);
        return queryMap;
    }

    /**
     * 根据流程实例id查询当前用户参与过的节点，不包含撤回和终止的节点
     * @param processid 流程实例id
     * @param user      操作用户
     * @return
     */
    @Override
    public List<Map<String, Object>> getCanRecallNode(String processid, UserVO user) {
        //所有参与过的流程
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processid).finished().or().taskAssignee(user.getId()).taskOwner(user.getId()).endOr().list();
        //当前任务
        List<Task> nowTasks = taskService.createTaskQuery().processInstanceId(processid).list();
        //当前任务所处节点
        Map<String, String> nowTaskDefKeys = new HashMap<String, String>();
        for (Task task : nowTasks) {
            nowTaskDefKeys.put(task.getTaskDefinitionKey(), task.getTaskDefinitionKey());
        }
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> mapTemp = new HashMap<String, Object>();//去重用的
        for (HistoricTaskInstance his : historicTaskInstances) {
            // 过滤掉撤销、终止和当前任务所处节点的记录
            if (!WorkflowContants.ProcessResult.RECALL.getValue().equals(his.getDescription()) && !WorkflowContants.ProcessResult.TERMINATE.getValue().equals(his.getDescription()) && !nowTaskDefKeys.containsKey(his.getTaskDefinitionKey())) {
                mapTemp.put(his.getTaskDefinitionKey(), his.getName());
            }
        }

        for (String key : mapTemp.keySet()) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("key", key);
            map.put("name", mapTemp.get(key));
            list.add(map);
        }
        return list;
    }

    /**
     * 参与人撤回流程
     *
     * @param params {'processId': 流程实例id,
     *               *  'recallNodeKey': 要撤回的节点key,
     *               *  'deleteReason': 撤回原因
     *               *  }
     * @param user
     * @param system
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recallMaster(Map<String, Object> params, UserVO user, UserVO system) throws Exception {
        String processid = params.get("processId") != null ? params.get("processId").toString() : "";
        String recallNodeKey = params.get("recallNodeKey") != null ? params.get("recallNodeKey").toString() : "";
        String deleteReason = params.get("deleteReason") != null ? params.get("deleteReason").toString() : "";
        if (StringUtils.isBlank(processid) || StringUtils.isBlank(recallNodeKey) || StringUtils.isBlank(deleteReason)) {
            throw new BusinessException("参数不正确");
        }
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().unfinished().processInstanceId(processid).singleResult();
        if (historicProcessInstance == null) {
            throw new BusinessException("流程已结束，无法撤回！");
        }
        ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
        if (definitionEntity == null) {
            throw new BusinessException("未查询到关联流程，无法撤回！");
        }

        //当前任务
        List<Task> oldTasks = taskService.createTaskQuery().processInstanceId(processid).list();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("assigne", user.getId());
        RollbackTaskCmd rCmd = new RollbackTaskCmd(oldTasks.get(0).getId(), recallNodeKey, user.getId(), variables, "", deleteReason, WorkflowContants.ProcessResult.RECALL.getValue(), false);
        managerService.executeCommand(rCmd);
        ActivityImpl recallActivity = definitionEntity.findActivity(recallNodeKey);
        Map<String, Object> mapProperties = recallActivity.getProperties();
        if (mapProperties.containsKey("multiInstance")) {
            //流程多实例，找到任意一条任务检出，删除其他任务
            List<Task> newTasks = taskService.createTaskQuery().processInstanceId(processid).list();
            if (!newTasks.isEmpty()) {
                taskService.claim(newTasks.get(0).getId(), user.getId());//检出第一条任务
                for (int i = 1; i < newTasks.size(); i++) {
                    taskService.claim(newTasks.get(i).getId(), system.getId());//检出任务至一个不存在的用户名下
                    taskService.complete(newTasks.get(i).getId());//完成该任务，查询时候过滤这些数据
                }
            }
        } else {
            //获取新任务,设置候选人（谁撤回的谁待办）
            List<Task> newTasks = taskService.createTaskQuery().processInstanceId(processid).list();
            for (Task newTask : newTasks) {
                taskService.claim(newTask.getId(), user.getId());//检出任务
            }
        }
    }


    /**
     * 流程查询、分页,只查询自己租户的
     * @param params
     * @param user
     * @return
     */
    @Override
    public PageUtils allProcessList(Map<String, Object> params, UserVO user) {
        int page = Integer.parseInt(params.get("page").toString());
        int limit = Integer.parseInt(params.get("limit").toString());
        String startUseName = params.get("startUseName") != null ? params.get("startUseName").toString() : "";
        String processName = params.get("processName") != null ? params.get("processName").toString() : "";
        String oper_time_start = params.get("oper_time_start") != null ? params.get("oper_time_start").toString() : "";
        String oper_time_end = params.get("oper_time_end") != null ? params.get("oper_time_end").toString() : "";
        String processState = params.get("processState") != null ? params.get("processState").toString() : "";
        String description = params.get("description") != null ? params.get("description").toString() : "";

        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
        //query.processInstanceTenantId(user.getTenantId());
        if (!"".equals(startUseName)) {
            query.variableValueLike("startUserName", "%" + startUseName.trim() + "%");
        }

        if (!"".equals(processName)) {
            query.processDefinitionName(processName);
        }

        if (!"".equals(description)) {
            query.processInstanceNameLike("%" + description + "%");
        }
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (!"".equals(oper_time_start)) {
                query.startedAfter(format.parse(oper_time_start + " 00:00:00"));
            }
            if (!"".equals(oper_time_end)) {
                query.startedBefore(format.parse(oper_time_end + " 23:59:59"));
            }
        } catch (Exception e) {
            throw new BusinessException("日期格式不对");
        }
        if (WorkflowContants.ProcessInstanceState.RUN.getValue().equals(processState)) {
            query.unfinished();
        } else if (WorkflowContants.ProcessInstanceState.END.getValue().equals(processState)) {
            query.finished();
            query.notDeleted();
        } else if (WorkflowContants.ProcessInstanceState.TERMINATED.getValue().equals(processState)) {
            query.deleted();
        }

        List<HistoricProcessInstance> list = query.orderByProcessInstanceStartTime().desc() // 创建历史流程实例查询
                .listPage((page - 1) * limit, limit);

        List<HistoryProcessVo> hpvList = new ArrayList<HistoryProcessVo>();
        for (HistoricProcessInstance hpi : list) {
            HistoryProcessVo historyProcessVo = new HistoryProcessVo((HistoricProcessInstanceEntity) hpi);
            List<HistoricVariableInstance> historicVariableInstances = historyService.createHistoricVariableInstanceQuery().processInstanceId(hpi.getId()).list();
            Map<String, Object> processVariables = new HashMap<>();
            for (HistoricVariableInstance hvi : historicVariableInstances) {
                processVariables.put(hvi.getVariableName(), hvi.getValue());
            }
            historyProcessVo.setProcessVariables(processVariables);
            historyProcessVo.setDescription(hpi.getName());
            if (historyProcessVo.getStartUserId() != null) {
                org.activiti.engine.identity.User assiginObjec = identityService.createUserQuery().userId(historyProcessVo.getStartUserId()).singleResult();
                if (assiginObjec != null) {
                    historyProcessVo.setStartUserName(assiginObjec.getLastName());
                }
            }
            hpvList.add(historyProcessVo);
        }
        int count = (int) query.count();
        PageUtils pageUtils = new PageUtils(hpvList, count);
        return pageUtils;
    }

    /**
     * 终止流程
     * @param processid
     * @param deleteReason
     * @param user
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProcess(String processid, String deleteReason, UserVO user) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processid)
                .finished().singleResult();
        if (historicProcessInstance != null) {
            throw new BusinessException("流程已结束，不能操作！");
        }
        runtimeService.setVariable(processid, "processInstanceState", WorkflowContants.ProcessInstanceState.TERMINATED.getValue());
        runtimeService.setVariable(processid, "wf_deleteUserId", user.getId());
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processid).singleResult();
        Execution execution = runtimeService.createExecutionQuery().processInstanceId(processid).executionId(processid).singleResult();
        ActivitiEvent event = ActivitiEventBuilder.createEvent(ActivitiEventType.ENTITY_SUSPENDED, execution.getId(), processInstance.getId(), processInstance.getProcessDefinitionId());
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processid).list();
        for (Task task : tasks) {
            task.setDescription(WorkflowContants.ProcessResult.TERMINATE.getValue());
            taskService.saveTask(task);
            // 添加删除原因
            taskService.addComment(task.getId(), processInstance.getId(), deleteReason);
            taskService.setAssignee(task.getId(), user.getId());
        }
        runtimeService.deleteProcessInstance(processid, deleteReason);
        runtimeService.dispatchEvent(event);
    }




    /**
     * 暂存审批意见
     * @param userId 用户id
     * @param taskId 任务id
     * @param approveAdvice 审批意见
     * @param authCatagory 是否代理
     * @param owner 授权人，authCatagory是‘1’时候
     */
    @Override
    public void saveApproveAdvice(String userId, String taskId, String approveAdvice, String authCatagory, String owner) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (StringUtils.isBlank(task.getAssignee())) {
            //受理人为空的先检出再改审批意见
            taskService.claim(taskId, userId);
            if ("1".equals(authCatagory)) {
                //如果是代理的情况，把拥有者改为授权人
                taskService.setOwner(taskId, owner);
            }
            taskService.addComment(task.getId(), task.getProcessInstanceId(), approveAdvice);
        } else if (userId.equals(task.getAssignee())) {
            //受理人是自己的修改审批意见
            List<Comment> comments = taskService.getTaskComments(taskId, "comment");
            for (Comment comment : comments) {
                taskService.deleteComment(comment.getId());
            }
            taskService.addComment(task.getId(), task.getProcessInstanceId(), approveAdvice);
        } else {
            //受理人不是自己的不让修改
            throw new BusinessException("该任务已被别人处理");
        }
    }

    /**
     * 根据当前流程任务id查询流程变量
     *
     * @param taskId
     * @return
     */
    @Override
    public Map<String, Object> getTaskParamByTaskId(String taskId) {
        return taskService.getVariables(taskId);
    }
}
